
#include "WebPage.h"

namespace SpiderWebKitClient {

// CookieJar

CookieJar::CookieJar(std::list<Cookie> cookies)
    :_cookies(cookies)
{
}

Cookie CookieJar::get(std::string name)
{
    std::list<Cookie>::iterator it;
    for (it = _cookies.begin(); it != _cookies.end(); it++) {
        if (it->name() == name) {
            return *it;
        }
    }
    return Cookie();
}

Cookie CookieJar::get(unsigned int index)
{
    if (index >= _cookies.size())
        return Cookie();

    int count = index;
    std::list<Cookie>::iterator it;
    for (it = _cookies.begin(); it != _cookies.end(); it++) {
        if (count == 0)
            return *it;
        count --;
    }

    return Cookie();
}

void CookieJar::set(std::string name, std::string value)
{
    bool hasOne = false;
    std::list<Cookie>::iterator it;
    for (it = _cookies.begin(); it != _cookies.end(); it++) {
        if (it->name() == name) {
            it->setValue(value);
            hasOne = true;
        }
    }

    if (!hasOne) {
        Cookie cookie;   
        cookie.setName(name);
        cookie.setValue(value);
        _cookies.push_back(cookie);
    }
}

void CookieJar::set(Cookie cookie)
{
    bool hasOne = false;
    std::list<Cookie>::iterator it;
    for (it = _cookies.begin(); it != _cookies.end(); it++) {
        if (it->name() == cookie.name()) {
            _cookies.erase(it);
            _cookies.push_back(cookie);
            hasOne = true;
        }
    }

    if (!hasOne)
        _cookies.push_back(cookie);
}

unsigned int CookieJar::size()
{
    return _cookies.size();
}

std::list<Cookie> CookieJar::cookies()
{
    return _cookies;
}

bool CookieJar::loadWithJson(std::string cookiesJson)
{
    Json::Value value(Json::arrayValue);
    Json::Reader reader;

    if (!reader.parse(cookiesJson, value))
        return false;

    for (unsigned int i = 0; i < value.size(); i ++)
        _cookies.push_back(value[i]);

    return true;
}

std::string CookieJar::toJson()
{
    Json::FastWriter writer;
    Json::Value root(Json::arrayValue);

    std::list<Cookie>::iterator it;
    for (it = _cookies.begin(); it != _cookies.end(); it ++)
        root.append(it->content());

    return writer.write(root);
}

std::string CookieJar::toString()
{
    std::string cookieHeader;
    for (int i = 0; i < size(); i ++) {
        Cookie c = get(i);
        cookieHeader.append(c.name());
        cookieHeader.append("=");
        cookieHeader.append(c.value());
        if (i != size()-1)
            cookieHeader.append(";");
    }

    return cookieHeader;
}

// CookieJar end

// Cookie

Cookie::Cookie(Json::Value content)
    :_content(content)
{
}

void Cookie::setDomain(std::string value)
{
    _content["domain"] = value;
}

bool Cookie::isNull()
{
    if (_content["name"].isNull() || _content["value"].isNull())
        return true;
    return false;
}

std::string Cookie::domain()
{
    if (_content["domain"].isNull())
        return "";
    return _content["domain"].asString();
}

void Cookie::setHttponly(bool value)
{
    _content["httponle"] = value;
}

bool Cookie::isHttponly()
{
    if (_content["httponly"].isNull())
        return true;
    return _content["httponly"].asBool();
}

void Cookie::setName(std::string value)
{
    _content["name"] = value;
}

std::string Cookie::name()
{
    return _content["name"].asString();
}

void Cookie::setValue(std::string value)
{
    _content["value"] = value;
}

std::string Cookie::value()
{
    return _content["value"].asString();
}

void Cookie::setPath(std::string value)
{
    _content["path"] = value;
}

std::string Cookie::path()
{
    if (_content["path"].isNull())
        return "/";
    return _content["path"].asString();
}

void Cookie::setSecure(bool value)
{
    _content["secure"] = value;
}

bool Cookie::secure()
{
    if (_content["secure"].isNull())
        return true;
    return _content["secure"].asBool();
}

void Cookie::setExpiry(double value)
{
    _content["expiry"] = value;
}

double Cookie::expiry()
{
    if (_content["expiry"].isNull())
        return 0;
    return _content["expiry"].asDouble();
}

std::string Cookie::expires()
{
    if (_content["expires"].isNull())
        return "";
    return _content["expires"].asString();
}

std::string Cookie::toJson()
{
    Json::FastWriter writer;
    return writer.write(_content);
}

Json::Value Cookie::content()
{
    return _content;
}

// Cookie end

// ResFilter

ResFilter::ResFilter()
{
}

ResFilter::ResFilter(std::list<std::string> rules)
    : m_rules(rules)
{
}

void ResFilter::append(std::string rule)
{
    bool hasOne = false;
    std::list<std::string>::iterator it;
    for (it = m_rules.begin(); it != m_rules.end(); it++)
        if ((*it) == rule)
            hasOne = true;

    if (!hasOne)
        m_rules.push_back(rule);
}

void ResFilter::remove(std::string rule)
{
    std::list<std::string>::iterator it;
    for (it = m_rules.begin(); it != m_rules.end(); it++)
        if ((*it) == rule)
            m_rules.erase(it);
}

unsigned int ResFilter::size()
{
    int count = 0;
    std::list<std::string>::iterator it;
    for (it = m_rules.begin(); it != m_rules.end(); it++)
        count ++;
}

std::string ResFilter::at(unsigned int index)
{
    int count = index;
    std::list<std::string>::iterator it;
    for (it = m_rules.begin(); it != m_rules.end(); it++) {
        if (count == 0)
            return (*it);
        count --;
    }

    return "";
}

std::string ResFilter::toJson()
{
    Json::FastWriter writer;
    Json::Value value(Json::arrayValue);

    std::list<std::string>::iterator it;
    for (it = m_rules.begin(); it != m_rules.end(); it++)
        value.append(*it);

    return writer.write(value);
}

// ResFilter end

WebPage::WebPage(long page, boost::shared_ptr<WebKitCaller> &caller, std::list<WebPage*> &pages, ResFilter filter)
    : m_caller(caller)
    , m_ref(page)
    , m_pages(pages)
    , m_isDestroy(false)
{
}

WebPage::~WebPage()
{
    destroy();
}

int WebPage::loadUrl( std::string address,
                      std::string operation,
                      bool sync,
                      int timeout,
                      int dtimeout,
                      std::map<std::string, std::string> headers,
                      std::string bodyString,
                      std::string encoding )
{
	long error = 0;
    long pageref = 0;
	std::string headerString;
    std::list<std::string> arglist;

	headerString = mapToJsonString(headers);

    std::string arg0 = boost::lexical_cast<std::string>(ref());
    std::string arg1 = boost::lexical_cast<std::string>((int)sync);
    std::string arg7 = boost::lexical_cast<std::string>(timeout);
    arglist.push_back(arg0);
    arglist.push_back(arg1);
    arglist.push_back(address);
    arglist.push_back(operation);
    arglist.push_back(headerString);
    arglist.push_back(bodyString);
    arglist.push_back(encoding);
    arglist.push_back(arg7);

    if (dtimeout != -1) {
        std::string arg8 = boost::lexical_cast<std::string>(dtimeout);
        arglist.push_back(arg8);
    }

    std::string retMessage = m_caller->webKitCall(ref(),
            WEBPAGE_VOID_LOADURL_LONG_REF_STRING_ADDRESS_STRING_OPERATION_QMAP_STRING_STRING_HEADERS_STRING_BODYSTRING_STRING_ENCODING,
            arglist, timeout + REQUEST_TIMEOUT);
    error = m_caller->getReturnPageValue(retMessage, &pageref);
    return error;
}

void WebPage::setHtml(std::string &html, std::string &url)
{
    std::string ret;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    arglist.push_back(html);
    arglist.push_back(url);
    m_caller->webKitCall(ref(), WEBPAGE_VOID_SETHTML_LONG_REF_STRING_HTML, arglist);
}

void WebPage::setSetting(std::string name, std::string setting)
{
    std::string ret;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    arglist.push_back(name);
    arglist.push_back(setting);
	m_caller->webKitCall(ref(), WEBPAGE_VOID_SETSETTING_LONG_REF_STRING_NAME_STRING_SETTING, arglist);
}

std::string WebPage::getTitle()
{
    std::string ret;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_STRING_GETTITLE_LONG_REF, arglist);

    ret = m_caller->getReturnStringValue(retMessage);

    return ret;
}

std::string WebPage::renderTreeDump()
{
    std::string ret;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_STRING_RENDERTREEDUMP_LONG_REF, arglist);
    ret = m_caller->getReturnStringValue(retMessage);

    return ret;
}

std::string WebPage::getDOMTreeSource()
{
    std::string ret;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_STRING_GETDOMTREESOURCE_LONG_REF, arglist);
    ret = m_caller->getReturnStringValue(retMessage);

    return ret;
}

std::string WebPage::getPageSource()
{
    std::string ret;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_STRING_GETPAGESOURCE_LONG_REF, arglist);
    ret = m_caller->getReturnStringValue(retMessage);

    return ret;
}

std::string WebPage::getUrl()
{
    std::string ret;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_STRING_GETURL_LONG_REF, arglist);
    ret = m_caller->getReturnStringValue(retMessage);

    return ret;
}

void WebPage::goBack()
{
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    m_caller->webKitCall(ref(), WEBPAGE_VOID_GOBACK_LONG_REF, arglist);
}

void WebPage::goForward()
{
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    m_caller->webKitCall(ref(), WEBPAGE_VOID_GOFORWARD_LONG_REF, arglist);
}

long WebPage::refresh()
{
    long ret = 0;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_LONG_REFRESH_LONG_REF, arglist);
    ret = m_caller->getReturnLongValue(retMessage);

    return ret;
}

WebElement WebPage::getElementById(std::string query)
{
    long elementRef = 0;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    arglist.push_back(query);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_LONG_GETELEMENTBYID_LONG_REF_STRING_QUERY, arglist);
    elementRef = m_caller->getReturnLongValue(retMessage);
    WebElement element(elementRef, ref(), m_caller.get());

    return element;
}

std::list<WebElement> WebPage::getElementsByTagName(std::string query)
{
    std::list<long> ret;
    std::list<WebElement> elements;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    arglist.push_back(query);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_LONG_GETELEMENTSBYTAGNAME_LONG_REF_STRING_QUERY, arglist);
    ret = m_caller->getReturnLongArrayValue(retMessage);

    std::list<long>::iterator it;
    for(it = ret.begin(); it != ret.end(); it ++) {
        WebElement e(*it, ref(), m_caller.get());
        elements.push_back(e);
    }

    return elements;
}

std::list<WebElement> WebPage::getElementsByName(std::string query)
{
    std::list<long> ret;
    std::list<WebElement> elements;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    arglist.push_back(query);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_LONG_GETELEMENTSBYNAME_LONG_REF_STRING_QUERY, arglist);
    ret = m_caller->getReturnLongArrayValue(retMessage);

    std::list<long>::iterator it;
    for(it = ret.begin(); it != ret.end(); it ++) {
        WebElement e(*it, ref(), m_caller.get());
        elements.push_back(e);
    }

    return elements;
}

std::list<WebElement> WebPage::getElementsByXpath(std::string query)
{
    std::list<long> ret;
    std::list<WebElement> elements;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    arglist.push_back(query);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_LONG_GETELEMENTSBYXPATH_LONG_REF_STRING_QUERY, arglist);
    ret = m_caller->getReturnLongArrayValue(retMessage);

    std::list<long>::iterator it;
    for(it = ret.begin(); it != ret.end(); it ++) {
        WebElement e(*it, ref(), m_caller.get());
        elements.push_back(e);
    }

    return elements;
}

WebElement WebPage::getElementByCssSelector(std::string query)
{
    long ret = 0;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    arglist.push_back(query);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_LONG_GETELEMENTBYCSSSELECTOR_LONG_REF_STRING_QUERY, arglist);
    ret = m_caller->getReturnLongValue(retMessage);
    WebElement element(ret, ref(), m_caller.get());

    return element;
}

std::list<WebElement> WebPage::getElementsByCssSelector(std::string query)
{
    std::list<long> ret;
    std::list<WebElement> elements;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    arglist.push_back(query);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_LONG_GETELEMENTSBYCSSSELECTOR_LONG_REF_STRING_QUERY, arglist);
    ret = m_caller->getReturnLongArrayValue(retMessage);

    std::list<long>::iterator it;
    for(it = ret.begin(); it != ret.end(); it ++) {
        WebElement e(*it, ref(), m_caller.get());
        elements.push_back(e);
    }

    return elements;
}

WebElement WebPage::activeElement()
{
    long elementRef = 0;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_LONG_ACTIVEELEMENT, arglist);
    elementRef = m_caller->getReturnLongValue(retMessage);
    WebElement element(elementRef, ref(), m_caller.get());

    return element;
}

long WebPage::selectFrameByName(std::string name)
{
    long ret = 0;
    std::list<std::string> arglist;

    arglist.push_back(name);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_LONG_SELECTFRAMEBYNAME_STRING_NAME, arglist);
    ret = m_caller->getReturnLongValue(retMessage);

    return ret;
}

long WebPage::selectFrameByIdx(long idx)
{
    long ret = 0;
    std::list<std::string> arglist;

    std::string Idx = boost::lexical_cast<std::string>(idx);
    arglist.push_back(Idx);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_LONG_SELECTFRAMEBYIDX_LONG_IDX, arglist);
    ret = m_caller->getReturnLongValue(retMessage);

    return ret;
}

std::string WebPage::getAlertText(bool clr)
{
    std::string ret;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    std::string clear = boost::lexical_cast<std::string>((int)clr);
    arglist.push_back(clear);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_STRING_GETALERTTEXT_LONG_REF_BOOL_CLR, arglist);
    ret = m_caller->getReturnStringValue(retMessage);

    return ret;
}

void WebPage::setViewportSize(int w, int h)
{
    std::list<std::string> arglist;

    std::string arg0 = boost::lexical_cast<std::string>(w);
    std::string arg1 = boost::lexical_cast<std::string>(h);
    arglist.push_back(arg0);
    arglist.push_back(arg1);
    m_caller->webKitCall(ref(), WEBPAGE_VOID_SETVIEWPORTSIZE_INT_W_INT_H, arglist);
}

// map to json like this: [{"xxx":"xxx"},{"yyy":"yyy"}]
std::string WebPage::mapToJsonString(std::map<std::string, std::string> &m)
{
	std::string jsonStr;
    Json::FastWriter writer;
    Json::Value root(Json::arrayValue);

	std::map<std::string, std::string>::iterator it;
	for (it = m.begin(); it != m.end(); it ++) {
        Json::Value value(Json::objectValue);
		value[it->first] = Json::Value(it->second);
        root.append(value);
	}

    jsonStr = writer.write(root);

	return jsonStr;
}

void WebPage::download(WebElement &element, std::string &link, std::map<std::string, std::string> &headers, int timeout)
{
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(element.ref());
    std::string time = boost::lexical_cast<std::string>(timeout);
    arglist.push_back(arg);
    arglist.push_back(time);
    std::string retMessage = m_caller->webKitCall(element.pageRef(), WEBPAGE_LONG_DOWNLOAD_LONG_REF, arglist);
    link = m_caller->getReturnDownloadInfoValue(retMessage, headers);
}

int WebPage::click(WebElement &element, int timeout)
{
    int error = 0;
    click(element, false, timeout, 0, error);
    return error;
}

int WebPage::click(WebElement &element, WebPage *&page, int timeout, int dtimeout)
{
    int error = 0;
    page = click(element, true, timeout, dtimeout, error);
    return error;
}

WebPage* WebPage::click(WebElement &element, bool targetBlank, int timeout, int dtimeout, int &error)
{
    if (element.pageRef() != ref())
        return NULL;

    if (!m_caller->checkAvailable()) {
        error = NOTAVALIABLE_LOAD_ERROR;
        return NULL;
    }

    long pageref = 0;
    WebPage *page = NULL;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(element.ref());
    std::string asy = boost::lexical_cast<std::string>(1);
    std::string tbk = boost::lexical_cast<std::string>((int)targetBlank);
    std::string time = boost::lexical_cast<std::string>(timeout);
    arglist.push_back(arg);
    arglist.push_back(asy);
    arglist.push_back(tbk);
    arglist.push_back(time);

    if (dtimeout != -1) {
        std::string dtime = boost::lexical_cast<std::string>(dtimeout);
        arglist.push_back(dtime);
    }

    std::string retMessage = m_caller->webKitCall(element.pageRef(), WEBELEMENT_LONG_CLICK_LONG_REF, arglist, timeout + REQUEST_TIMEOUT);
    error = m_caller->getReturnPageValue(retMessage, &pageref);

    if (error < 0) {
        return NULL;
    }

    if (ref() != pageref) {
        page = new WebPage(pageref, m_caller, m_pages, m_resFilter);
        m_pages.insert(m_pages.begin(), page);
    }

    return page;
}

int WebPage::sendKeys(WebElement &element, std::string type, long keys, int timeout)
{
    int error = 0;
    sendKeys(element, type, keys, false, timeout, 0, error);
    return error;
}

int WebPage::sendKeys(WebElement &element, std::string type, long keys, WebPage *&page, int timeout, int dtimeout)
{
    int error = 0;
    page = sendKeys(element, type, keys, true, timeout, dtimeout, error);
    return error;
}

WebPage* WebPage::sendKeys(WebElement &element, std::string type, long keys, bool openNewPage, int timeout, int dtimeout, int &error)
{
    long pageref = 0;
    WebPage *page = NULL;
    std::list<std::string> arglist;

    if (!m_caller->checkAvailable()) {
        error = NOTAVALIABLE_LOAD_ERROR;
        return NULL;
    }

    std::string arg = boost::lexical_cast<std::string>(element.ref());
    std::string val = boost::lexical_cast<std::string>(keys);
    std::string asy = boost::lexical_cast<std::string>(1);
    std::string onp = boost::lexical_cast<std::string>((int)openNewPage);
    std::string time = boost::lexical_cast<std::string>(timeout);
    arglist.push_back(arg);
    arglist.push_back(type);
    arglist.push_back(val);
    arglist.push_back(asy);
    arglist.push_back(onp);
    arglist.push_back(time);

    if (dtimeout != -1) {
        std::string dtime = boost::lexical_cast<std::string>(dtimeout);
        arglist.push_back(dtime);
    }

    std::string retMessage = m_caller->webKitCall(element.pageRef(), WEBELEMENT_LONG_SENDKEYS_LONG_REF_STRING_TYPE_LONG_KEYS, arglist, timeout + REQUEST_TIMEOUT);
    error = m_caller->getReturnPageValue(retMessage, &pageref);

    if (pageref == 0) {
        return NULL;
    }

    if (ref() != pageref) {
        page = new WebPage(pageref, m_caller, m_pages, m_resFilter);
        m_pages.insert(m_pages.begin(), page);
    }

    return page;
}

void WebPage::mouseMove(WebElement element)
{
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(element.ref());
    arglist.push_back(arg);
    m_caller->webKitCall(ref(), WEBPAGE_VOID_MOUSEMOVE_LONG_REF, arglist);
}

void WebPage::mouseMove(int x, int y)
{
    std::list<std::string> arglist;

    std::string arg0 = boost::lexical_cast<std::string>(x);
    std::string arg1 = boost::lexical_cast<std::string>(y);
    arglist.push_back(arg0);
    arglist.push_back(arg1);
    m_caller->webKitCall(ref(), WEBPAGE_VOID_MOUSEMOVE_INT_X_INT_Y, arglist);
}

long WebPage::setCookies(std::list<Cookie> cookies)
{
    Json::FastWriter writer;
    Json::Value root(Json::arrayValue);
    std::list<std::string> arglist;

    std::list<Cookie>::iterator it;
    for (it = cookies.begin(); it != cookies.end(); it ++)
        root.append(it->content());

    std::string cookiesString = writer.write(root);
    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    arglist.push_back(cookiesString);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_LONG_SETCOOKIE_LONG_REF_STRING_COOKIES, arglist);
    return m_caller->getReturnLongValue(retMessage);
}

std::list<Cookie> WebPage::getCookies()
{
    std::list<Cookie> cookies;
    std::list<Json::Value> ret;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_STRING_COOKIES_LONG_REF, arglist);
    ret = m_caller->getReturnJsonObjArrayValue(retMessage);

    std::list<Json::Value>::iterator it;
    for (it = ret.begin(); it != ret.end(); it++) {
        cookies.push_back(Cookie(*it));
    }
    
    return cookies;
}

CookieJar WebPage::getCookieJar()
{
    CookieJar jar(getCookies());
    return jar;
}

long WebPage::deleteCookie(std::string name)
{
    long ret;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    arglist.push_back(name);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_LONG_DELETECOOKIE_LONG_REF_STRING_CNAME, arglist);
    ret = m_caller->getReturnLongValue(retMessage);
    return ret;
}

void WebPage::destroy()
{
    if (m_isDestroy)
        return;

    long ret = 0;
    std::list<std::string> arglist;

    std::string arg = boost::lexical_cast<std::string>(ref());
    arglist.push_back(arg);
    std::string retMessage = m_caller->webKitCall(ref(), WEBKIT_LONG_DESTROY_LONG_REF, arglist);
    ret = m_caller->getReturnLongValue(retMessage);
    
    m_isDestroy = true;
}

std::string WebPage::getStateInfo()
{
    std::string ret;
    std::list<std::string> arglist;

    std::string retMessage = m_caller->webKitCall(0, WEBKIT_STRING_GETSTATEINFO, arglist);
    ret = m_caller->getReturnStringValue(retMessage);

    return ret;
}

bool WebPage::webPageImageBuffer(std::vector<char> &output)
{
    bool ret;
    std::list<std::string> arglist;

    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_STRING_RENDER_IMAGE_BASE64, arglist);
    ret = m_caller->getReturnBufferValue(retMessage, output);

    return ret;
}

bool WebPage::setDestroyTime(int timeMS)
{
    long ret;
    std::list<std::string> arglist;

    std::string time = boost::lexical_cast<std::string>(timeMS);
    arglist.push_back(time);
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_LONG_SET_DESTROY_TIME, arglist);
    ret = m_caller->getReturnLongValue(retMessage);

    return ret;
}

bool WebPage::waitForCssSelector(std::string query, unsigned int times)
{
    if (isFailed())
        return false;

    unsigned int count = times;
    while (count) {
        std::list<WebElement> elist = getElementsByCssSelector(query);
        if (elist.size() <= 0) {
            usleep(200000);
            count --;
        } else
            return true;
    }

    return false;
}

void WebPage::scroll(int x, int y)
{
    std::list<std::string> arglist;

    std::string argx = boost::lexical_cast<std::string>(x);
    std::string argy = boost::lexical_cast<std::string>(y);
    arglist.push_back(argx);
    arglist.push_back(argy);
    m_caller->webKitCall(ref(), WEBPAGE_VOID_SCROLL, arglist);
}

void WebPage::setFilterRule(ResFilter filter)
{
    std::list<std::string> arglist;
    arglist.push_back(m_resFilter.toJson());
    m_caller->webKitCall(ref(), WEBPAGE_VOID_SETFILTERRULE_STRING_RULES, arglist);
}

std::string WebPage::postData()
{
    std::list<std::string> arglist;
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_STRING_POSTDATA_LONG_REF, arglist);
    return m_caller->getReturnStringValue(retMessage);
}

std::string WebPage::method()
{
    std::list<std::string> arglist;
    std::string retMessage = m_caller->webKitCall(ref(), WEBPAGE_STRING_METHOD_LONG_REF, arglist);
    return m_caller->getReturnStringValue(retMessage);
}

bool WebPage::isFailed()
{
    return m_caller->failed();
}

} // namespace SpiderWebKitClient

